package cn.kgc.shiro03.shiro;

import cn.kgc.shiro03.entity.*;
import cn.kgc.shiro03.mapper.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author: mosin
 * @version: v1.0  2022/11/28
 */
public class CustomerRealm extends AuthorizingRealm {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private RolePersMapper rolePersMapper;
    @Autowired
    private PermissionMapper permissionMapper;
    // 授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        //获取用户身份信息 查询用户角色 权限字符串
        String primaryPrincipal = (String) principals.getPrimaryPrincipal();

        LambdaQueryWrapper<User> lambda = new QueryWrapper<User>().lambda();
        lambda.eq(User::getUsername, primaryPrincipal);
        User user = userMapper.selectOne(lambda);
        Integer userId = user.getId();

        // 2.根据用户id 查询 角色id
        LambdaQueryWrapper<UserRole> lambd = new QueryWrapper<UserRole>().lambda();
        lambd.eq(UserRole::getUserId, userId);
        List<UserRole> userRoles = userRoleMapper.selectList(lambd);


        List<Integer> roleIds = userRoles.stream().map(userRole -> {
            return userRole.getRoleId();
        }).collect(Collectors.toList());

        // 根据角色id  查询角色名字  role_name   admin super
        List<Role> roles = roleMapper.selectBatchIds(roleIds);

        List<String> roleNames = roles.stream().map(role -> {
            return role.getRoleName();
        }).collect(Collectors.toList());

        System.out.println("roleNames = " + roleNames);

        // 3.根据角色id  查询权限id
        QueryWrapper<RolePers> rolePersQueryWrapper = new QueryWrapper<>();
        rolePersQueryWrapper.in("role_id", roleIds);
        List<RolePers> rolePers = rolePersMapper.selectList(rolePersQueryWrapper);

        List<Integer> perIds = rolePers.stream().map(rp -> {
            return rp.getPerId();
        }).collect(Collectors.toList());

        LambdaQueryWrapper<Permission> perLambda = new QueryWrapper<Permission>().lambda();
        perLambda.in(Permission::getId, perIds);
        List<Permission> permissions = permissionMapper.selectList(perLambda);

        // 遍历集合 获取权限字符串
        List<String> permissionStr = permissions.stream().map(permission -> {
                return permission.getPermission() ;
        }).filter(pstr->pstr!=null).collect(Collectors.toList());

        System.out.println("permissionStr = " + permissionStr);

        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.addRoles(roleNames);
        simpleAuthorizationInfo.addStringPermissions(permissionStr);

        return simpleAuthorizationInfo;
    }

    // 认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

        String principal = (String) token.getPrincipal();
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("username", principal);
        User user = userMapper.selectOne(userQueryWrapper);
        if(user!=null){
            //判定用户是否被锁定
            if(user.getState()==0){
                throw  new LockedAccountException();
            }
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), ByteSource.Util.bytes(user.getSalt()), this.getName());
            return  simpleAuthenticationInfo;
        }
        return null;
    }
}
